#pragma once

#include <QtWidgets/QWidget>
#include "ExD3DWidget.h"
#include "ExGameObject.h"
#include "ExCamera.h"

class ExMainHUD : public ExD3DWidget
{
	Q_OBJECT

public:

	ExMainHUD(QWidget* parent = Q_NULLPTR);

	virtual bool Init() override;
	virtual void OnResize() override;                  // 该父类方法需要在窗口大小变动的时候调用
	virtual void UpdateScene(float dt) override;       // 子类需要实现该方法，完成每一帧的更新
	virtual void DrawScene() override;                // 子类需要实现该方法，完成每一帧的绘制

protected:

	bool InitEffect();

	bool InitResource();

protected:

	ComPtr<ID2D1SolidColorBrush> m_pColorBrush;	    // 单色笔刷
	ComPtr<IDWriteFont> m_pFont;					// 字体
	ComPtr<IDWriteTextFormat> m_pTextFormat;		// 文本格式

	ComPtr<ID3D11InputLayout> m_pVertexLayout2D;	// 用于2D的顶点输入布局
	ComPtr<ID3D11InputLayout> m_pVertexLayout3D;	// 用于3D的顶点输入布局
	ComPtr<ID3D11Buffer> m_pConstantBuffers[4];				    // 常量缓冲区

	ExGameObject m_WoodCrate;									// 木盒
	ExGameObject m_Floor;										// 地板
	std::vector<ExGameObject> m_Walls;							// 墙壁

	ComPtr<ID3D11VertexShader> m_pVertexShader3D;				// 用于3D的顶点着色器
	ComPtr<ID3D11PixelShader> m_pPixelShader3D;				    // 用于3D的像素着色器
	ComPtr<ID3D11VertexShader> m_pVertexShader2D;				// 用于2D的顶点着色器
	ComPtr<ID3D11PixelShader> m_pPixelShader2D;				    // 用于2D的像素着色器

	CBChangesEveryFrame m_CBFrame;							    // 该缓冲区存放仅在每一帧进行更新的变量
	CBChangesOnResize m_CBOnResize;							    // 该缓冲区存放仅在窗口大小变化时更新的变量
	CBChangesRarely m_CBRarely;								    // 该缓冲区存放不会再进行修改的变量
	
	ComPtr<ID3D11SamplerState> m_pSamplerState;				    // 采样器状态
	
	std::shared_ptr<ExFreeCamera> m_pCamera;						// 摄像机



	// 临时代码
	ComPtr<ID3D11Buffer> m_pVertexBuffer;		// 顶点缓冲区
	ComPtr<ID3D11Buffer> m_pIndexBuffer;		// 索引缓冲区

	template<class VertexType>
	bool ResetMesh(const ExGeometry::MeshData<VertexType>& meshData);

	void ResetBox();
};



template<class VertexType>
bool ExMainHUD::ResetMesh(const ExGeometry::MeshData<VertexType>& meshData)
{
	m_pVertexBuffer.Reset();
	m_pIndexBuffer.Reset();

	// 设置顶点缓冲区描述
	D3D11_BUFFER_DESC vbd;
	ZeroMemory(&vbd, sizeof(vbd));
	vbd.Usage = D3D11_USAGE_IMMUTABLE;
	vbd.ByteWidth = (UINT)meshData.vertexVec.size() * sizeof(VertexType);
	vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vbd.CPUAccessFlags = 0;
	// 新建顶点缓冲区
	D3D11_SUBRESOURCE_DATA InitData;
	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = meshData.vertexVec.data();
	HR(m_pd3dDevice->CreateBuffer(&vbd, &InitData, m_pVertexBuffer.GetAddressOf()));


	// 输入装配阶段的顶点缓冲区设置
	UINT stride = sizeof(VertexType);	// 跨越字节数
	UINT offset = 0;						// 起始偏移量
	m_pd3dImmediateContext->IASetVertexBuffers(0, 1, m_pVertexBuffer.GetAddressOf(), &stride, &offset);

	// 设置索引缓冲区描述
	D3D11_BUFFER_DESC ibd;
	ZeroMemory(&ibd, sizeof(ibd));
	ibd.Usage = D3D11_USAGE_IMMUTABLE;
	ibd.ByteWidth = (UINT)meshData.indexVec.size() * sizeof(DWORD);
	ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
	ibd.CPUAccessFlags = 0;
	// 新建索引缓冲区
	InitData.pSysMem = meshData.indexVec.data();
	HR(m_pd3dDevice->CreateBuffer(&ibd, &InitData, m_pIndexBuffer.GetAddressOf()));
	// 输入装配阶段的索引缓冲区设置
	m_pd3dImmediateContext->IASetIndexBuffer(m_pIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);

	return true;
}

void ExMainHUD::ResetBox()
{
	
}